﻿#ifndef MIRAGON_TESTS_TESTS_HPP
#define MIRAGON_TESTS_TESTS_HPP

#include <cstddef>
#include <functional>
#include <iostream>
#include <string>
#include <vector>

namespace miragon {

using TestRoutine = std::function<void(void)>;
using TestRoutineList = std::vector<TestRoutine>;

struct TestCase {
    std::string name;
    TestRoutine routine;

    TestCase(void);
    TestCase(const std::string& name, TestRoutine routine);
};

using TestCaseList = std::vector<TestCase>;
using TestCaseAssertList = std::vector<std::string>;

class TestRunner {
public:
    // Constructor
    TestRunner(void);

    // Add test case to root
    void add(const TestCase& t);

    // Run all test cases
    int runAll(void);

    // Get test case list
    TestCaseList& testCases(void);

    // Get last assert list
    TestCaseAssertList& lastAsserts(void);

    // Get singleton instance
    static TestRunner& instance();

private:
    // Hold all test cases
    TestCaseList mTestCases;

    // Hold all asserts for last runned test case
    TestCaseAssertList mLastAsserts;
};

// Define a test case routine
#define TEST_CASE(name)                                                        \
    static void testcase_##name();                                             \
    static TestCase s_testcase_##name = {#name, testcase_##name};              \
    static void testcase_##name()

template<typename T>
void expect_equal(T& a, T& b, const char* expr);

template<typename T> 
void expect_equal(const T& a, const T& b, const char* expr);

void expect_starts_with(const std::string& target, const std::string& pattern,
                        const char* expr);

/*
#define expect_equal(a, b, assert)                                             \
    if ((a) != (b))                                                            \
        TestRunner::instance().lastAsserts().push_back(assert);

#define expect_notequal(a, b, assert)                                          \
    if ((a) == (b))                                                            \
        TestRunner::instance().lastAsserts().push_back(assert);

#define expect_ptrref_notnull(p, assert)                                       \
    if (p.get() == NULL)                                                       \
        TestRunner::instance().lastAsserts().push_back(assert);
*/

} // namespace miragon

#endif // MIRAGON_TESTS_TESTS_HPP
